
package com.hlkj.pay.app.merchant.ext.impl.lakala.handler;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.http.template.OkHttpTemplate;
import com.hlkj.pay.app.merchant.ext.dto.access.ChannelMerchantAccessContext;
import com.hlkj.pay.app.merchant.ext.dto.access.ChannelMerchantAccessQueryContext;
import com.hlkj.pay.app.merchant.ext.impl.lakala.dto.LakalaAccessExtentDto;
import com.hlkj.pay.app.merchant.ext.impl.lakala.dto.LakalaConfig;
import com.hlkj.pay.app.merchant.ext.impl.lakala.dto.resp.LakalaAccessQueryRes;
import com.hlkj.pay.app.merchant.ext.impl.lakala.dto.resp.LakalaAccessSubmitRes;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessInfoDO;
import com.hlkj.pay.infrastructure.model.pay.PayChannelRequestDO;
import com.hlkj.pay.util.RSAUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author HlpayTeam
 * @date 2024/10/16 9:10
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class LakalaMerchantAccessInfoHandler extends LakalaMerchantCommonParamsHandle {

    private final LakalaMerchantParamsHandle lakalaMerchantParamsHandle;

    private final OkHttpTemplate okHttpTemplate;

    /**
     *
     * @param channelMerchantAccessContext
     */
    public void merchantAccess(ChannelMerchantAccessContext channelMerchantAccessContext) {
        CommonResult<LakalaConfig> lakalaConfigCommonResult = lakalaMerchantParamsHandle.lakalaConfig(channelMerchantAccessContext.getProviderChannelConfig(),
                channelMerchantAccessContext.isTest());
        if (!lakalaConfigCommonResult.isSuccess()) {
            channelMerchantAccessContext.setProcessStatus(false);
            channelMerchantAccessContext.setRemark(lakalaConfigCommonResult.getMsg());
            return;
        }
        LakalaConfig lakalaConfig = lakalaConfigCommonResult.getData();
        CommonResult<Void> paramsCheckResult = lakalaMerchantParamsHandle.merchantApplyParamsCheck(channelMerchantAccessContext);
        if (!paramsCheckResult.isSuccess()) {
            channelMerchantAccessContext.setProcessStatus(false);
            channelMerchantAccessContext.setRemark(paramsCheckResult.getMsg());
            return;
        }
        try {
            MerchantAccessInfoDO merchantAccessInfo = channelMerchantAccessContext.getMerchantAccessDto().getMerchantAccessInfo();
            if (StringUtils.hasText(merchantAccessInfo.getSubMchId())) {
                log.info("拉卡拉重新提交进件 请求参数 requestId:{}", merchantAccessInfo.getRequestId());
                merchantAccessInfo.setSubMchId("");
            }
            lakalaMerchantParamsHandle.addProcessFileId(channelMerchantAccessContext, lakalaConfig);
            Map<String, Object> params = lakalaMerchantParamsHandle.merchantApplyParams(channelMerchantAccessContext, lakalaConfig);
            String accessUrl = lakalaMerchantParamsHandle.accessUrl(channelMerchantAccessContext.isTest());
            Map<String, String> headerMap = lakalaMerchantParamsHandle.headerMap(lakalaConfig, channelMerchantAccessContext.isTest());
            String jsonString = JsonUtils.toJsonString(params);
            PayChannelRequestDO payChannelRequestDO = channelMerchantAccessContext.getPayChannelRequestDO();
            log.info("拉卡拉 提交进件 请求参数 :{}", jsonString);
            payChannelRequestDO.setRequestParams(jsonString);
            String post = okHttpTemplate.post(accessUrl, jsonString, headerMap);
            payChannelRequestDO.setResponse(post);
            log.info("拉卡拉 提交进件 返回参数:{}", post);
            LakalaAccessSubmitRes lakalaAccessRes = JsonUtils.parseObject(post, LakalaAccessSubmitRes.class);
            if (StringUtils.isEmpty(lakalaAccessRes.getMerchantNo())) {
                channelMerchantAccessContext.setProcessStatus(false);
                channelMerchantAccessContext.setRemark(lakalaAccessRes.getMessage());
            }
            else {
                merchantAccessInfo.setSubMchId(lakalaAccessRes.getMerchantNo());
                // 提交进件完就是审核
                channelMerchantAccessContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.AUDIT);
                channelMerchantAccessContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.CHANNEL_APPROVE);
            }

        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("拉卡拉 提交进件 异常 :{}", e.getMessage(), e);
            channelMerchantAccessContext.setProcessStatus(false);
            channelMerchantAccessContext.setRemark(e.getMessage());
        }
    }

    /**
     * 进件查询
     *
     * @param channelMerchantAccessQueryContext
     */
    public void accessTermQueryRequest(ChannelMerchantAccessQueryContext channelMerchantAccessQueryContext) {
        CommonResult<LakalaConfig> lakalaConfigCommonResult = lakalaMerchantParamsHandle.lakalaConfig(channelMerchantAccessQueryContext.getProviderChannelConfig(),
                channelMerchantAccessQueryContext.isTest());
        if (!lakalaConfigCommonResult.isSuccess()) {
            channelMerchantAccessQueryContext.setProcessStatus(false);
            channelMerchantAccessQueryContext.setRemark(lakalaConfigCommonResult.getMsg());
            return;
        }
        MerchantAccessInfoDO merchantAccessInfo = channelMerchantAccessQueryContext.getMerchantAccessInfo();
        LakalaConfig lakalaConfig = lakalaConfigCommonResult.getData();
        Map<String, Object> params = new HashMap<>();
        params.put("customerNo", merchantAccessInfo.getSubMchId());
        String paramsString = JsonUtils.toJsonString(params);
        String accessQueryUrl = lakalaMerchantParamsHandle.accessTermQueryUrl(channelMerchantAccessQueryContext.isTest());
        Map<String, String> headerMap = lakalaMerchantParamsHandle.headerMap(lakalaConfig, channelMerchantAccessQueryContext.isTest());
        String jsonString = JsonUtils.toJsonString(params);
        try {
            String req = RSAUtil.encryptByPrivateKey(paramsString, lakalaConfig.getSassPrivateKey());
            Map<String, Object> data = new HashMap<>();
            data.put("data", req);
            log.info("拉卡拉 已绑定终端信息查询 请求参数:{}", jsonString);
            String post = okHttpTemplate.post(accessQueryUrl, JsonUtils.toJsonString(data), headerMap);
            Map<String, String> responseData = JsonUtils.parseObject(post, Map.class);
            String response = RSAUtil.decryptByPublicKey(responseData.get("data"), lakalaConfig.getSassPublicKey());
            log.info("拉卡拉 已绑定终端信息查询 返回参数:{}", response);

            // 商户状态 OPEN:开通，CLOSE:关闭，LOSS:流失,WAIT_AUDI:审核中,REJECT:审核拒绝,REVIEW_FAIL:复核失败,
            // REVIEW_AUDIT:复核审核中,ACTIVITY:激活
            // 进件会返回一个内部商户编号customerNo，用这个内部商编获取商户信息会返回一个外部商户编号externalCustomerNo，这个外部商编就是银联商户号。
            LakalaAccessQueryRes lakalaAccessRes = JsonUtils.parseObject(response, LakalaAccessQueryRes.class);
            LakalaAccessQueryRes.CustomerBean customer = lakalaAccessRes.getCustomer();
            switch (customer.getCustomerStatus()) {
                case "OPEN":
                case "ACTIVITY":
                    merchantAccessInfo.setExtendA(customer.getExternalCustomerNo());
                    channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.WAIT_SET);
                    // 获取报备信息
                    channelMerchantAccessQueryContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.SUBMERINFO);
                    break;
                case "CLOSE":
                case "LOSS":
                case "REJECT":
                case "REVIEW_FAIL":
                    channelMerchantAccessQueryContext.setProcessStatus(false);
                    channelMerchantAccessQueryContext.setRemark(customer.getAuditRemark());
                    channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.APPROVE_REFUSE);
                    break;
                case "WAIT_AUDI":
                case "REVIEW_AUDIT":
                    // channelMerchantAccessQueryContext.setProcessStatus(false);
                    channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.CHANNEL_APPROVE);
                    break;
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            channelMerchantAccessQueryContext.setProcessStatus(false);
            channelMerchantAccessQueryContext.setRemark(e.getMessage());
        }
    }

    /**
     * 进件查询
     *
     * @param channelMerchantAccessQueryContext
     */
    public void accessQueryRequest(ChannelMerchantAccessQueryContext channelMerchantAccessQueryContext) {
        CommonResult<LakalaConfig> lakalaConfigCommonResult = lakalaMerchantParamsHandle.lakalaConfig(channelMerchantAccessQueryContext.getProviderChannelConfig(),
                channelMerchantAccessQueryContext.isTest());
        if (!lakalaConfigCommonResult.isSuccess()) {
            channelMerchantAccessQueryContext.setProcessStatus(false);
            channelMerchantAccessQueryContext.setRemark(lakalaConfigCommonResult.getMsg());
            return;
        }
        MerchantAccessInfoDO merchantAccessInfo = channelMerchantAccessQueryContext.getMerchantAccessInfo();
        LakalaConfig lakalaConfig = lakalaConfigCommonResult.getData();
        Map<String, Object> params = new HashMap<>();
        params.put("customerNo", merchantAccessInfo.getSubMchId());

        String paramsString = JsonUtils.toJsonString(params);
        String accessQueryUrl = lakalaMerchantParamsHandle.accessQueryUrl(channelMerchantAccessQueryContext.isTest());
        Map<String, String> headerMap = lakalaMerchantParamsHandle.headerMap(lakalaConfig, channelMerchantAccessQueryContext.isTest());
        String jsonString = JsonUtils.toJsonString(params);
        try {
            String req = RSAUtil.encryptByPrivateKey(paramsString, lakalaConfig.getSassPrivateKey());
            Map<String, Object> data = new HashMap<>();
            data.put("data", req);
            log.info("拉卡拉 进件查询 请求参数:{}", jsonString);
            String post = okHttpTemplate.post(accessQueryUrl, JsonUtils.toJsonString(data), headerMap);
            Map<String, String> responseData = JsonUtils.parseObject(post, Map.class);
            String response = RSAUtil.decryptByPublicKey(responseData.get("data"), lakalaConfig.getSassPublicKey());
            log.info("拉卡拉 进件查询 返回参数:{}", response);

            // 商户状态 OPEN:开通，CLOSE:关闭，LOSS:流失,WAIT_AUDI:审核中,REJECT:审核拒绝,REVIEW_FAIL:复核失败,
            // REVIEW_AUDIT:复核审核中,ACTIVITY:激活
            // 进件会返回一个内部商户编号customerNo，用这个内部商编获取商户信息会返回一个外部商户编号externalCustomerNo，这个外部商编就是银联商户号。
            LakalaAccessQueryRes lakalaAccessRes = JsonUtils.parseObject(response, LakalaAccessQueryRes.class);
            LakalaAccessQueryRes.CustomerBean customer = lakalaAccessRes.getCustomer();
            LakalaAccessExtentDto lakalaAccessExtentDto = new LakalaAccessExtentDto();
            switch (customer.getCustomerStatus()) {
                case "OPEN":
                case "ACTIVITY":
                    lakalaAccessExtentDto.setMerCupNo(customer.getExternalCustomerNo());
                    lakalaAccessExtentDto.setCustomerNo(merchantAccessInfo.getSubMchId());
                    if(!StringUtils.hasText(merchantAccessInfo.getExtendA())){
                        merchantAccessInfo.setSubMchId(lakalaAccessExtentDto.getMerCupNo());
                    }
                    channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.WAIT_SET);
                    // 获取报备信息
                    channelMerchantAccessQueryContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.SUBMERINFO);
                    break;
                case "CLOSE":
                case "LOSS":
                case "REJECT":
                case "REVIEW_FAIL":
                    channelMerchantAccessQueryContext.setProcessStatus(false);
                    channelMerchantAccessQueryContext.setRemark(customer.getAuditRemark());
                    channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.APPROVE_REFUSE);
                    break;
                case "WAIT_AUDI":
                case "REVIEW_AUDIT":
                    // channelMerchantAccessQueryContext.setProcessStatus(false);
                    channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.CHANNEL_APPROVE);
                    break;
            }
            List<LakalaAccessQueryRes.TerminalInfoBean> terminalInfo = lakalaAccessRes.getTerminalInfo();
            if (!CollectionUtils.isEmpty(terminalInfo)) {
                LakalaAccessQueryRes.TerminalInfoBean terminalInfoBean = terminalInfo.get(0);
                List<LakalaAccessQueryRes.TerminalInfoBean.ActiveNoVoListBean> activeNoVoList = terminalInfoBean.getActiveNoVoList();
                if (!CollectionUtils.isEmpty(activeNoVoList)) {
                    List<LakalaAccessQueryRes.TerminalInfoBean.ActiveNoVoListBean> collect = activeNoVoList.stream()
                            .filter(activeNoVoListBean -> "QR_CODE_CARD".equals(activeNoVoListBean.getBusiTypeCode())).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(collect)) {
                        lakalaAccessExtentDto.setTermNo(collect.get(0).getTermNo());
                    }
                    else {
                        lakalaAccessExtentDto.setTermNo(activeNoVoList.get(0).getTermNo());
                    }
                }
                else {
                    lakalaAccessExtentDto.setTermNo(customer.getTermNo());
                }
            }
            else {
                lakalaAccessExtentDto.setTermNo(customer.getTermNo());
            }
            merchantAccessInfo.setExtendA(JsonUtils.toJsonString(lakalaAccessExtentDto));

        }
        catch (Exception e) {
            e.printStackTrace();
            channelMerchantAccessQueryContext.setProcessStatus(false);
            channelMerchantAccessQueryContext.setRemark(e.getMessage());
        }
    }

}
